home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / cpu / adsp2100 / 2100ops.c < prev    next >
Text File  |  1999-10-27  |  44KB  |  1,470 lines

  1. /*===========================================================================
  2.     ASTAT -- ALU/MAC status register
  3. ===========================================================================*/
  4.  
  5. /* flag definitions */
  6. #define SSFLAG            0x80
  7. #define MVFLAG            0x40
  8. #define QFLAG            0x20
  9. #define SFLAG            0x10
  10. #define CFLAG            0x08
  11. #define VFLAG            0x04
  12. #define NFLAG            0x02
  13. #define ZFLAG            0x01
  14.  
  15. /* extracts flags */
  16. #define GET_SS            (adsp2100.astat & SSFLAG)
  17. #define GET_MV            (adsp2100.astat & MVFLAG)
  18. #define GET_Q            (adsp2100.astat &  QFLAG)
  19. #define GET_S            (adsp2100.astat &  SFLAG)
  20. #define GET_C            (adsp2100.astat &  CFLAG)
  21. #define GET_V            (adsp2100.astat &  VFLAG)
  22. #define GET_N            (adsp2100.astat &  NFLAG)
  23. #define GET_Z            (adsp2100.astat &  ZFLAG)
  24.  
  25. /* clears flags */
  26. #define CLR_SS            (adsp2100.astat &= ~SSFLAG)
  27. #define CLR_MV            (adsp2100.astat &= ~MVFLAG)
  28. #define CLR_Q            (adsp2100.astat &=  ~QFLAG)
  29. #define CLR_S            (adsp2100.astat &=  ~SFLAG)
  30. #define CLR_C            (adsp2100.astat &=  ~CFLAG)
  31. #define CLR_V            (adsp2100.astat &=  ~VFLAG)
  32. #define CLR_N            (adsp2100.astat &=  ~NFLAG)
  33. #define CLR_Z            (adsp2100.astat &=  ~ZFLAG)
  34.  
  35. /* sets flags */
  36. #define SET_SS            (adsp2100.astat |= SSFLAG)
  37. #define SET_MV            (adsp2100.astat |= MVFLAG)
  38. #define SET_Q            (adsp2100.astat |=  QFLAG)
  39. #define SET_S            (adsp2100.astat |=  SFLAG)
  40. #define SET_C            (adsp2100.astat |=  CFLAG)
  41. #define SET_V            (adsp2100.astat |=  VFLAG)
  42. #define SET_Z            (adsp2100.astat |=  ZFLAG)
  43. #define SET_N            (adsp2100.astat |=  NFLAG)
  44.  
  45. /* flag clearing; must be done before setting */
  46. #define CLR_FLAGS        (adsp2100.astat &= adsp2100.astat_clear)
  47.  
  48. /* compute flags */
  49. #define CALC_Z(r)        (adsp2100.astat |= ((r & 0xffff) == 0))
  50. #define CALC_N(r)        (adsp2100.astat |= (r >> 14) & 0x02)
  51. #define CALC_V(s,d,r)    (adsp2100.astat |= ((s ^ d ^ r ^ (r >> 1)) >> 13) & 0x04)
  52. #define CALC_C(r)        (adsp2100.astat |= (r >> 13) & 0x08)
  53. #define CALC_C_SUB(r)    (adsp2100.astat |= (~r >> 13) & 0x08)
  54. #define CALC_NZ(r)         CLR_FLAGS; CALC_N(r); CALC_Z(r)
  55. #define CALC_NZV(s,d,r) CLR_FLAGS; CALC_N(r); CALC_Z(r); CALC_V(s,d,r)
  56. #define CALC_NZVC(s,d,r) CLR_FLAGS; CALC_N(r); CALC_Z(r); CALC_V(s,d,r); CALC_C(r)
  57. #define CALC_NZVC_SUB(s,d,r) CLR_FLAGS; CALC_N(r); CALC_Z(r); CALC_V(s,d,r); CALC_C_SUB(r)
  58.  
  59.  
  60.  
  61. /*===========================================================================
  62.     MSTAT -- ALU/MAC control register
  63. ===========================================================================*/
  64.  
  65. /* flag definitions */
  66. #define MSTAT_BANK        0x01            /* register bank select */
  67. #define MSTAT_REVERSE    0x02            /* bit-reverse addressing enable (DAG1) */
  68. #define MSTAT_STICKYV    0x04            /* sticky ALU overflow enable */
  69. #define MSTAT_SATURATE    0x08            /* AR saturation mode enable */
  70.  
  71. #if SUPPORT_2101_EXTENSIONS
  72. #define MSTAT_INTEGER    0x10            /* MAC result placement; 0=fractional, 1=integer */
  73. #define MSTAT_TIMER        0x20            /* timer enable */
  74. #define MSTAT_GOMODE    0x40            /* go mode enable */
  75. #endif
  76.  
  77. /* call this whenever mstat changes */
  78. INLINE void mstat_changed(void)
  79. {
  80.     core = &adsp2100.r[adsp2100.mstat & MSTAT_BANK];
  81.     if (adsp2100.mstat & MSTAT_STICKYV)
  82.         adsp2100.astat_clear = ~(CFLAG | NFLAG | ZFLAG);
  83.     else 
  84.         adsp2100.astat_clear = ~(CFLAG | VFLAG | NFLAG | ZFLAG);
  85. }
  86.  
  87.  
  88. /*===========================================================================
  89.     SSTAT -- stack status register
  90. ===========================================================================*/
  91.  
  92. /* flag definitions */
  93. #define PC_EMPTY        0x01            /* PC stack empty */
  94. #define PC_OVER            0x02            /* PC stack overflow */
  95. #define COUNT_EMPTY        0x04            /* count stack empty */
  96. #define COUNT_OVER        0x08            /* count stack overflow */
  97. #define STATUS_EMPTY    0x10            /* status stack empty */
  98. #define STATUS_OVER        0x20            /* status stack overflow */
  99. #define LOOP_EMPTY        0x40            /* loop stack empty */
  100. #define LOOP_OVER        0x80            /* loop stack overflow */
  101.  
  102.  
  103.  
  104. /*===========================================================================
  105.     PC stack handlers
  106. ===========================================================================*/
  107.  
  108. INLINE UINT16 pc_stack_top(void)
  109. {
  110.     if (adsp2100.pc_sp > 0)
  111.         return adsp2100.pc_stack[adsp2100.pc_sp - 1];
  112.     else
  113.         return adsp2100.pc_stack[0];
  114. }
  115.  
  116. INLINE void pc_stack_push(void)
  117. {
  118.     if (adsp2100.pc_sp < PC_STACK_DEPTH)
  119.     {
  120.         adsp2100.pc_stack[adsp2100.pc_sp] = adsp2100.pc;
  121.         adsp2100.pc_sp++;
  122.         adsp2100.sstat &= ~PC_EMPTY;
  123.     }
  124.     else
  125.         adsp2100.sstat |= PC_OVER;
  126. }
  127.  
  128. INLINE void pc_stack_pop(void)
  129. {
  130.     if (adsp2100.pc_sp > 0)
  131.     {
  132.         adsp2100.pc_sp--;
  133.         if (adsp2100.pc_sp == 0)
  134.             adsp2100.sstat |= PC_EMPTY;
  135.     }
  136.     adsp2100.pc = adsp2100.pc_stack[adsp2100.pc_sp];
  137. }
  138.  
  139. INLINE void pc_stack_pop_nop(void)
  140. {
  141.     if (adsp2100.pc_sp > 0)
  142.     {
  143.         adsp2100.pc_sp--;
  144.         if (adsp2100.pc_sp == 0)
  145.             adsp2100.sstat |= PC_EMPTY;
  146.     }
  147. }
  148.  
  149.  
  150. /*===========================================================================
  151.     CNTR stack handlers
  152. ===========================================================================*/
  153.  
  154. INLINE UINT16 cntr_stack_top(void)
  155. {
  156.     if (adsp2100.cntr_sp > 0)
  157.         return adsp2100.cntr_stack[adsp2100.cntr_sp - 1];
  158.     else
  159.         return adsp2100.cntr_stack[0];
  160. }
  161.  
  162. INLINE void cntr_stack_push(void)
  163. {
  164.     if (adsp2100.cntr_sp < CNTR_STACK_DEPTH)
  165.     {
  166.         adsp2100.cntr_stack[adsp2100.cntr_sp] = adsp2100.cntr;
  167.         adsp2100.cntr_sp++;
  168.         adsp2100.sstat &= ~COUNT_EMPTY;
  169.     }
  170.     else
  171.         adsp2100.sstat |= COUNT_OVER;
  172. }
  173.  
  174. INLINE void cntr_stack_pop(void)
  175. {
  176.     if (adsp2100.cntr_sp > 0)
  177.     {
  178.         adsp2100.cntr_sp--;
  179.         if (adsp2100.cntr_sp == 0)
  180.             adsp2100.sstat |= COUNT_EMPTY;
  181.     }
  182.     adsp2100.cntr = adsp2100.cntr_stack[adsp2100.cntr_sp];
  183. }
  184.  
  185.  
  186. /*===========================================================================
  187.     LOOP stack handlers
  188. ===========================================================================*/
  189.  
  190. INLINE UINT32 loop_stack_top(void)
  191. {
  192.     if (adsp2100.loop_sp > 0)
  193.         return adsp2100.loop_stack[adsp2100.loop_sp - 1];
  194.     else
  195.         return adsp2100.loop_stack[0];
  196. }
  197.  
  198. INLINE void loop_stack_push(UINT32 value)
  199. {
  200.     if (adsp2100.loop_sp < LOOP_STACK_DEPTH)
  201.     {
  202.         adsp2100.loop_stack[adsp2100.loop_sp] = value;
  203.         adsp2100.loop_sp++;
  204.         adsp2100.loop = value >> 4;
  205.         adsp2100.loop_condition = value & 15;
  206.         adsp2100.sstat &= ~LOOP_EMPTY;
  207.     }
  208.     else
  209.         adsp2100.sstat |= LOOP_OVER;
  210. }
  211.  
  212. INLINE void loop_stack_pop(void)
  213. {
  214.     if (adsp2100.loop_sp > 0)
  215.     {
  216.         adsp2100.loop_sp--;
  217.         if (adsp2100.loop_sp == 0)
  218.         {
  219.             adsp2100.loop = 0xffff;
  220.             adsp2100.loop_condition = 0;
  221.             adsp2100.sstat |= LOOP_EMPTY;
  222.         }
  223.         else
  224.         {
  225.             adsp2100.loop = adsp2100.loop_stack[adsp2100.loop_sp -1] >> 4;
  226.             adsp2100.loop_condition = adsp2100.loop_stack[adsp2100.loop_sp - 1] & 15;
  227.         }
  228.     }
  229. }
  230.  
  231.  
  232. /*===========================================================================
  233.     STAT stack handlers
  234. ===========================================================================*/
  235.  
  236. INLINE void stat_stack_push(void)
  237. {
  238.     if (adsp2100.stat_sp < STAT_STACK_DEPTH)
  239.     {
  240.         adsp2100.stat_stack[adsp2100.stat_sp][0] = adsp2100.mstat;
  241.         adsp2100.stat_stack[adsp2100.stat_sp][1] = adsp2100.imask;
  242.         adsp2100.stat_stack[adsp2100.stat_sp][2] = adsp2100.astat;
  243.         adsp2100.stat_sp++;
  244.         adsp2100.sstat &= ~STATUS_EMPTY;
  245.     }
  246.     else
  247.         adsp2100.sstat |= STATUS_OVER;
  248. }
  249.  
  250. INLINE void stat_stack_pop(void)
  251. {
  252.     if (adsp2100.stat_sp > 0)
  253.     {
  254.         adsp2100.stat_sp--;
  255.         if (adsp2100.stat_sp == 0)
  256.             adsp2100.sstat |= STATUS_EMPTY;
  257.     }
  258.     adsp2100.mstat = adsp2100.stat_stack[adsp2100.stat_sp][0]; mstat_changed();
  259.     adsp2100.imask = adsp2100.stat_stack[adsp2100.stat_sp][1]; check_irqs();
  260.     adsp2100.astat = adsp2100.stat_stack[adsp2100.stat_sp][2];
  261. }
  262.  
  263.  
  264.  
  265. /*===========================================================================
  266.     condition code checking
  267. ===========================================================================*/
  268.  
  269. static int cond_eq(void) { return (adsp2100.astat & ZFLAG); }
  270. static int cond_ne(void) { return (~adsp2100.astat & ZFLAG); }
  271. static int cond_lt(void) { return (adsp2100.astat & NFLAG) ^ ((adsp2100.astat & VFLAG) >> 1); }
  272. static int cond_ge(void) { return (~adsp2100.astat & NFLAG) ^ ((adsp2100.astat & VFLAG) >> 1); }
  273. static int cond_le(void) { return ((adsp2100.astat & NFLAG) ^ ((adsp2100.astat & VFLAG) >> 1)) | ((adsp2100.astat & ZFLAG) << 1); }
  274. static int cond_gt(void) { return ((~adsp2100.astat & NFLAG) ^ ((adsp2100.astat & VFLAG) >> 1)) & ((~adsp2100.astat & ZFLAG) << 1); }
  275. static int cond_ac(void) { return (adsp2100.astat & CFLAG); }
  276. static int cond_notac(void) { return (~adsp2100.astat & CFLAG); }
  277. static int cond_av(void) { return (adsp2100.astat & VFLAG); }
  278. static int cond_notav(void) { return (~adsp2100.astat & VFLAG); }
  279. static int cond_mv(void) { return (adsp2100.astat & MVFLAG); }
  280. static int cond_notmv(void) { return (~adsp2100.astat & MVFLAG); }
  281. static int cond_neg(void) { return (adsp2100.astat & NFLAG); }
  282. static int cond_pos(void) { return (~adsp2100.astat & NFLAG); }
  283. static int cond_notce(void) { if (--adsp2100.cntr == 0) { cntr_stack_pop(); return 1; } return 0; }
  284. static int cond_true(void) { return 1; }
  285.  
  286. #define CONDITION(c) ((*condition[c])())
  287.  
  288. static int (*condition[16])(void) =
  289. {
  290.     cond_eq, cond_ne, cond_gt, cond_le,
  291.     cond_lt, cond_ge, cond_av, cond_notav, 
  292.     cond_ac, cond_notac, cond_neg, cond_pos, 
  293.     cond_mv, cond_notmv, cond_notce, cond_true
  294. };
  295.  
  296.  
  297.  
  298. /*===========================================================================
  299.     register writing
  300. ===========================================================================*/
  301.  
  302. INLINE UINT16 recompute_mask(UINT16 l)
  303. {
  304.     UINT16 mask = 0x3fff;
  305.     l = ((l - 1) << 1) | 1;
  306.     while ((l & 0x4000) == 0) mask >>= 1, l <<= 1;
  307.     return mask;
  308. }
  309.  
  310. static void wr_inval(INT32 val) { }
  311. static void wr_ax0(INT32 val)   { core->ax0.s = val; }
  312. static void wr_ax1(INT32 val)   { core->ax1.s = val; }
  313. static void wr_mx0(INT32 val)   { core->mx0.s = val; }
  314. static void wr_mx1(INT32 val)   { core->mx1.s = val; }
  315. static void wr_ay0(INT32 val)   { core->ay0.s = val; }
  316. static void wr_ay1(INT32 val)   { core->ay1.s = val; }
  317. static void wr_my0(INT32 val)   { core->my0.s = val; }
  318. static void wr_my1(INT32 val)   { core->my1.s = val; }
  319. static void wr_si(INT32 val)    { core->si.s = val; }
  320. static void wr_se(INT32 val)    { core->se.s = (INT8)val; }
  321. static void wr_ar(INT32 val)    { core->ar.s = val; }
  322. static void wr_mr0(INT32 val)   { core->mr.mrx.mr0.s = val; }
  323. static void wr_mr1(INT32 val)   { core->mr.mrx.mr1.s = val; core->mr.mrx.mr2.s = (INT16)val >> 15; }
  324. static void wr_mr2(INT32 val)   { core->mr.mrx.mr2.s = (INT8)val; }
  325. static void wr_sr0(INT32 val)   { core->sr.srx.sr0.s = val; }
  326. static void wr_sr1(INT32 val)   { core->sr.srx.sr1.s = val; }
  327. static void wr_i0(INT32 val)    { adsp2100.i[0] = val & 0x3fff; adsp2100.base[0] = (val & 0x3fff) & ~adsp2100.lmask[0]; }
  328. static void wr_i1(INT32 val)    { adsp2100.i[1] = val & 0x3fff; adsp2100.base[1] = (val & 0x3fff) & ~adsp2100.lmask[1]; }
  329. static void wr_i2(INT32 val)    { adsp2100.i[2] = val & 0x3fff; adsp2100.base[2] = (val & 0x3fff) & ~adsp2100.lmask[2]; }
  330. static void wr_i3(INT32 val)    { adsp2100.i[3] = val & 0x3fff; adsp2100.base[3] = (val & 0x3fff) & ~adsp2100.lmask[3]; }
  331. static void wr_i4(INT32 val)    { adsp2100.i[4] = val & 0x3fff; adsp2100.base[4] = (val & 0x3fff) & ~adsp2100.lmask[4]; }
  332. static void wr_i5(INT32 val)    { adsp2100.i[5] = val & 0x3fff; adsp2100.base[5] = (val & 0x3fff) & ~adsp2100.lmask[5]; }
  333. static void wr_i6(INT32 val)    { adsp2100.i[6] = val & 0x3fff; adsp2100.base[6] = (val & 0x3fff) & ~adsp2100.lmask[6]; }
  334. static void wr_i7(INT32 val)    { adsp2100.i[7] = val & 0x3fff; adsp2100.base[7] = (val & 0x3fff) & ~adsp2100.lmask[7]; }
  335. static void wr_m0(INT32 val)    { adsp2100.m[0] = (INT16)(val << 2) >> 2; }
  336. static void wr_m1(INT32 val)    { adsp2100.m[1] = (INT16)(val << 2) >> 2; }
  337. static void wr_m2(INT32 val)    { adsp2100.m[2] = (INT16)(val << 2) >> 2; }
  338. static void wr_m3(INT32 val)    { adsp2100.m[3] = (INT16)(val << 2) >> 2; }
  339. static void wr_m4(INT32 val)    { adsp2100.m[4] = (INT16)(val << 2) >> 2; }
  340. static void wr_m5(INT32 val)    { adsp2100.m[5] = (INT16)(val << 2) >> 2; }
  341. static void wr_m6(INT32 val)    { adsp2100.m[6] = (INT16)(val << 2) >> 2; }
  342. static void wr_m7(INT32 val)    { adsp2100.m[7] = (INT16)(val << 2) >> 2; }
  343. static void wr_l0(INT32 val)    { adsp2100.l[0] = val & 0x3fff; adsp2100.lmask[0] = recompute_mask(val & 0x3fff); adsp2100.base[0] = (adsp2100.i[0] & 0x3fff) & ~adsp2100.lmask[0]; }
  344. static void wr_l1(INT32 val)    { adsp2100.l[1] = val & 0x3fff; adsp2100.lmask[1] = recompute_mask(val & 0x3fff); adsp2100.base[1] = (adsp2100.i[1] & 0x3fff) & ~adsp2100.lmask[1]; }
  345. static void wr_l2(INT32 val)    { adsp2100.l[2] = val & 0x3fff; adsp2100.lmask[2] = recompute_mask(val & 0x3fff); adsp2100.base[2] = (adsp2100.i[2] & 0x3fff) & ~adsp2100.lmask[2]; }
  346. static void wr_l3(INT32 val)    { adsp2100.l[3] = val & 0x3fff; adsp2100.lmask[3] = recompute_mask(val & 0x3fff); adsp2100.base[3] = (adsp2100.i[3] & 0x3fff) & ~adsp2100.lmask[3]; }
  347. static void wr_l4(INT32 val)    { adsp2100.l[4] = val & 0x3fff; adsp2100.lmask[4] = recompute_mask(val & 0x3fff); adsp2100.base[4] = (adsp2100.i[4] & 0x3fff) & ~adsp2100.lmask[4]; }
  348. static void wr_l5(INT32 val)    { adsp2100.l[5] = val & 0x3fff; adsp2100.lmask[5] = recompute_mask(val & 0x3fff); adsp2100.base[5] = (adsp2100.i[5] & 0x3fff) & ~adsp2100.lmask[5]; }
  349. static void wr_l6(INT32 val)    { adsp2100.l[6] = val & 0x3fff; adsp2100.lmask[6] = recompute_mask(val & 0x3fff); adsp2100.base[6] = (adsp2100.i[6] & 0x3fff) & ~adsp2100.lmask[6]; }
  350. static void wr_l7(INT32 val)    { adsp2100.l[7] = val & 0x3fff; adsp2100.lmask[7] = recompute_mask(val & 0x3fff); adsp2100.base[7] = (adsp2100.i[7] & 0x3fff) & ~adsp2100.lmask[7]; }
  351. static void wr_astat(INT32 val) { adsp2100.astat = val & 0x00ff; }
  352. #if SUPPORT_2101_EXTENSIONS
  353. static void wr_mstat(INT32 val) { adsp2100.mstat = val & 0x007f; mstat_changed(); }
  354. #else
  355. static void wr_mstat(INT32 val) { adsp2100.mstat = val & 0x000f; mstat_changed(); }
  356. #endif
  357. static void wr_sstat(INT32 val) { adsp2100.sstat = val & 0x00ff; }
  358. static void wr_imask(INT32 val) { adsp2100.imask = val & 0x000f; check_irqs(); }
  359. static void wr_icntl(INT32 val) { adsp2100.icntl = val & 0x001f; check_irqs(); }
  360. static void wr_cntr(INT32 val)  { cntr_stack_push(); adsp2100.cntr = val & 0x3fff; }
  361. static void wr_sb(INT32 val)    { core->sb.s = (INT16)(val << 11) >> 11; }
  362. static void wr_px(INT32 val)    { adsp2100.px = val; }
  363.  
  364. #define WRITE_REG(grp,reg,val) ((*wr_reg[grp][reg])(val))
  365.  
  366. static void (*wr_reg[4][16])(INT32) =
  367. {
  368.     {
  369.         wr_ax0, wr_ax1, wr_mx0, wr_mx1, wr_ay0, wr_ay1, wr_my0, wr_my1, 
  370.         wr_si, wr_se, wr_ar, wr_mr0, wr_mr1, wr_mr2, wr_sr0, wr_sr1
  371.     },
  372.     {
  373.         wr_i0, wr_i1, wr_i2, wr_i3, wr_m0, wr_m1, wr_m2, wr_m3,
  374.         wr_l0, wr_l1, wr_l2, wr_l3, wr_inval, wr_inval, wr_inval, wr_inval
  375.     },
  376.     {
  377.         wr_i4, wr_i5, wr_i6, wr_i7, wr_m4, wr_m5, wr_m6, wr_m7,
  378.         wr_l4, wr_l5, wr_l6, wr_l7, wr_inval, wr_inval, wr_inval, wr_inval
  379.     },
  380.     {
  381.         wr_astat, wr_mstat, wr_inval, wr_imask, wr_icntl, wr_cntr, wr_sb, wr_px,
  382.         wr_inval, wr_inval, wr_inval, wr_inval, wr_inval, wr_inval, wr_inval, wr_inval
  383.     }
  384. };
  385.         
  386.  
  387.  
  388. /*===========================================================================
  389.     register reading
  390. ===========================================================================*/
  391.  
  392. static INT32 rd_inval(void) { return 0; }
  393. static INT32 rd_ax0(void)   { return core->ax0.s; }
  394. static INT32 rd_ax1(void)   { return core->ax1.s; }
  395. static INT32 rd_mx0(void)   { return core->mx0.s; }
  396. static INT32 rd_mx1(void)   { return core->mx1.s; }
  397. static INT32 rd_ay0(void)   { return core->ay0.s; }
  398. static INT32 rd_ay1(void)   { return core->ay1.s; }
  399. static INT32 rd_my0(void)   { return core->my0.s; }
  400. static INT32 rd_my1(void)   { return core->my1.s; }
  401. static INT32 rd_si(void)    { return core->si.s; }
  402. static INT32 rd_se(void)    { return core->se.s; }
  403. static INT32 rd_ar(void)    { return core->ar.s; }
  404. static INT32 rd_mr0(void)   { return core->mr.mrx.mr0.s; }
  405. static INT32 rd_mr1(void)   { return core->mr.mrx.mr1.s; }
  406. static INT32 rd_mr2(void)   { return core->mr.mrx.mr2.s; }
  407. static INT32 rd_sr0(void)   { return core->sr.srx.sr0.s; }
  408. static INT32 rd_sr1(void)   { return core->sr.srx.sr1.s; }
  409. static INT32 rd_i0(void)    { return adsp2100.i[0]; }
  410. static INT32 rd_i1(void)    { return adsp2100.i[1]; }
  411. static INT32 rd_i2(void)    { return adsp2100.i[2]; }
  412. static INT32 rd_i3(void)    { return adsp2100.i[3]; }
  413. static INT32 rd_i4(void)    { return adsp2100.i[4]; }
  414. static INT32 rd_i5(void)    { return adsp2100.i[5]; }
  415. static INT32 rd_i6(void)    { return adsp2100.i[6]; }
  416. static INT32 rd_i7(void)    { return adsp2100.i[7]; }
  417. static INT32 rd_m0(void)    { return adsp2100.m[0]; }
  418. static INT32 rd_m1(void)    { return adsp2100.m[1]; }
  419. static INT32 rd_m2(void)    { return adsp2100.m[2]; }
  420. static INT32 rd_m3(void)    { return adsp2100.m[3]; }
  421. static INT32 rd_m4(void)    { return adsp2100.m[4]; }
  422. static INT32 rd_m5(void)    { return adsp2100.m[5]; }
  423. static INT32 rd_m6(void)    { return adsp2100.m[6]; }
  424. static INT32 rd_m7(void)    { return adsp2100.m[7]; }
  425. static INT32 rd_l0(void)    { return adsp2100.l[0]; }
  426. static INT32 rd_l1(void)    { return adsp2100.l[1]; }
  427. static INT32 rd_l2(void)    { return adsp2100.l[2]; }
  428. static INT32 rd_l3(void)    { return adsp2100.l[3]; }
  429. static INT32 rd_l4(void)    { return adsp2100.l[4]; }
  430. static INT32 rd_l5(void)    { return adsp2100.l[5]; }
  431. static INT32 rd_l6(void)    { return adsp2100.l[6]; }
  432. static INT32 rd_l7(void)    { return adsp2100.l[7]; }
  433. static INT32 rd_astat(void) { return adsp2100.astat; }
  434. #if SUPPORT_2101_EXTENSIONS
  435. static INT32 rd_mstat(void) { return adsp2100.mstat; }
  436. #else
  437. static INT32 rd_mstat(void) { return adsp2100.mstat; }
  438. #endif
  439. static INT32 rd_sstat(void) { return adsp2100.sstat; }
  440. static INT32 rd_imask(void) { return adsp2100.imask; }
  441. static INT32 rd_icntl(void) { return adsp2100.icntl; }
  442. static INT32 rd_cntr(void)  { return adsp2100.cntr; }
  443. static INT32 rd_sb(void)    { return core->sb.s; }
  444. static INT32 rd_px(void)    { return adsp2100.px; }
  445.  
  446.  
  447. #define READ_REG(grp,reg) ((*rd_reg[grp][reg])())
  448.  
  449. static INT32 (*rd_reg[4][16])(void) =
  450. {
  451.     {
  452.         rd_ax0, rd_ax1, rd_mx0, rd_mx1, rd_ay0, rd_ay1, rd_my0, rd_my1, 
  453.         rd_si, rd_se, rd_ar, rd_mr0, rd_mr1, rd_mr2, rd_sr0, rd_sr1
  454.     },
  455.     {
  456.         rd_i0, rd_i1, rd_i2, rd_i3, rd_m0, rd_m1, rd_m2, rd_m3,
  457.         rd_l0, rd_l1, rd_l2, rd_l3, rd_inval, rd_inval, rd_inval, rd_inval
  458.     },
  459.     {
  460.         rd_i4, rd_i5, rd_i6, rd_i7, rd_m4, rd_m5, rd_m6, rd_m7,
  461.         rd_l4, rd_l5, rd_l6, rd_l7, rd_inval, rd_inval, rd_inval, rd_inval
  462.     },
  463.     {
  464.         rd_astat, rd_mstat, rd_sstat, rd_imask, rd_icntl, rd_cntr, rd_sb, rd_px,
  465.         rd_inval, rd_inval, rd_inval, rd_inval, rd_inval, rd_inval, rd_inval, rd_inval
  466.     }
  467. };
  468.         
  469.  
  470.  
  471. /*===========================================================================
  472.     Modulus addressing logic
  473. ===========================================================================*/
  474.  
  475. INLINE void modify_address(UINT32 ireg, UINT32 mreg)
  476. {
  477.     UINT32 base = adsp2100.base[ireg];
  478.     UINT32 i = adsp2100.i[ireg];
  479.     UINT32 l = adsp2100.l[ireg];
  480.     
  481.     i += adsp2100.m[mreg];
  482.     if (i < base) i += l;
  483.     else if (i >= base + l) i -= l;
  484.     adsp2100.i[ireg] = i;
  485. }
  486.  
  487.  
  488.  
  489. /*===========================================================================
  490.     Data memory accessors
  491. ===========================================================================*/
  492.  
  493. INLINE void data_write(UINT32 ireg, UINT32 mreg, INT32 val)
  494. {
  495.     UINT32 base = adsp2100.base[ireg];
  496.     UINT32 i = adsp2100.i[ireg];
  497.     UINT32 l = adsp2100.l[ireg];
  498.     
  499.     WWORD_DATA(i, val);
  500.     
  501.     i += adsp2100.m[mreg];
  502.     if (i < base) i += l;
  503.     else if (i >= base + l) i -= l;
  504.     adsp2100.i[ireg] = i;
  505. }
  506.         
  507.  
  508. INLINE UINT16 data_read(UINT32 ireg, UINT32 mreg)
  509. {
  510.     UINT32 base = adsp2100.base[ireg];
  511.     UINT32 i = adsp2100.i[ireg];
  512.     UINT32 l = adsp2100.l[ireg];
  513.  
  514.     UINT16 res = RWORD_DATA(i);
  515.     
  516.     i += adsp2100.m[mreg];
  517.     if (i < base) i += l;
  518.     else if (i >= base + l) i -= l;
  519.     adsp2100.i[ireg] = i;
  520.     
  521.     return res;
  522. }
  523.         
  524.  
  525.  
  526. /*===========================================================================
  527.     Program memory accessors
  528. ===========================================================================*/
  529.  
  530. INLINE void pgm_write(UINT32 ireg, UINT32 mreg, INT32 val)
  531. {
  532.     UINT32 base = adsp2100.base[ireg];
  533.     UINT32 i = adsp2100.i[ireg];
  534.     UINT32 l = adsp2100.l[ireg];
  535.     
  536.     WWORD_PGM(i, (val << 8) | adsp2100.px);
  537.  
  538.     i += adsp2100.m[mreg];
  539.     if (i < base) i += l;
  540.     else if (i >= base + l) i -= l;
  541.     adsp2100.i[ireg] = i;
  542. }
  543.         
  544.  
  545. INLINE UINT16 pgm_read(UINT32 ireg, UINT32 mreg)
  546. {
  547.     UINT32 base = adsp2100.base[ireg];
  548.     UINT32 i = adsp2100.i[ireg];
  549.     UINT32 l = adsp2100.l[ireg];
  550.     UINT32 res;
  551.  
  552.     res = RWORD_PGM(i);
  553.     adsp2100.px = res;
  554.     res >>= 8;
  555.     
  556.     i += adsp2100.m[mreg];
  557.     if (i < base) i += l;
  558.     else if (i >= base + l) i -= l;
  559.     adsp2100.i[ireg] = i;
  560.     
  561.     return res;
  562. }
  563.         
  564.  
  565.  
  566. /*===========================================================================
  567.     ALU register reading
  568. ===========================================================================*/
  569.  
  570. #define ALU_GETXREG_UNSIGNED(x) (*(UINT16 *)((UINT8 *)core + alu_xregs[x]))
  571. #define ALU_GETXREG_SIGNED(x)   (*( INT16 *)((UINT8 *)core + alu_xregs[x]))
  572. #define ALU_GETYREG_UNSIGNED(y) (*(UINT16 *)((UINT8 *)core + alu_yregs[y]))
  573. #define ALU_GETYREG_SIGNED(y)   (*( INT16 *)((UINT8 *)core + alu_yregs[y]))
  574.  
  575. static const UINT32 alu_xregs[8] =
  576. {
  577.     offsetof(ADSPCORE, ax0),
  578.     offsetof(ADSPCORE, ax1),
  579.     offsetof(ADSPCORE, ar),
  580.     offsetof(ADSPCORE, mr.mrx.mr0),
  581.     offsetof(ADSPCORE, mr.mrx.mr1),
  582.     offsetof(ADSPCORE, mr.mrx.mr2),
  583.     offsetof(ADSPCORE, sr.srx.sr0),
  584.     offsetof(ADSPCORE, sr.srx.sr1)
  585. };
  586.  
  587. static const UINT32 alu_yregs[4] =
  588. {
  589.     offsetof(ADSPCORE, ay0),
  590.     offsetof(ADSPCORE, ay1),
  591.     offsetof(ADSPCORE, af),
  592.     offsetof(ADSPCORE, zero)
  593. };
  594.  
  595.  
  596.  
  597. /*===========================================================================
  598.     MAC register reading
  599. ===========================================================================*/
  600.  
  601. #define MAC_GETXREG_UNSIGNED(x) (*(UINT16 *)((UINT8 *)core + mac_xregs[x]))
  602. #define MAC_GETXREG_SIGNED(x)   (*( INT16 *)((UINT8 *)core + mac_xregs[x]))
  603. #define MAC_GETYREG_UNSIGNED(y) (*(UINT16 *)((UINT8 *)core + mac_yregs[y]))
  604. #define MAC_GETYREG_SIGNED(y)   (*( INT16 *)((UINT8 *)core + mac_yregs[y]))
  605.  
  606. static const UINT32 mac_xregs[8] =
  607. {
  608.     offsetof(ADSPCORE, mx0),
  609.     offsetof(ADSPCORE, mx1),
  610.     offsetof(ADSPCORE, ar),
  611.     offsetof(ADSPCORE, mr.mrx.mr0),
  612.     offsetof(ADSPCORE, mr.mrx.mr1),
  613.     offsetof(ADSPCORE, mr.mrx.mr2),
  614.     offsetof(ADSPCORE, sr.srx.sr0),
  615.     offsetof(ADSPCORE, sr.srx.sr1)
  616. };
  617.  
  618. static const UINT32 mac_yregs[4] =
  619. {
  620.     offsetof(ADSPCORE, my0),
  621.     offsetof(ADSPCORE, my1),
  622.     offsetof(ADSPCORE, mf),
  623.     offsetof(ADSPCORE, zero)
  624. };
  625.  
  626.  
  627.  
  628. /*===========================================================================
  629.     SHIFT register reading
  630. ===========================================================================*/
  631.  
  632. #define SHIFT_GETXREG_UNSIGNED(x) (*(UINT16 *)((UINT8 *)core + shift_xregs[x]))
  633. #define SHIFT_GETXREG_SIGNED(x)   (*( INT16 *)((UINT8 *)core + shift_xregs[x]))
  634.  
  635. static const UINT32 shift_xregs[8] =
  636. {
  637.     offsetof(ADSPCORE, si),
  638.     offsetof(ADSPCORE, si),
  639.     offsetof(ADSPCORE, ar),
  640.     offsetof(ADSPCORE, mr.mrx.mr0),
  641.     offsetof(ADSPCORE, mr.mrx.mr1),
  642.     offsetof(ADSPCORE, mr.mrx.mr2),
  643.     offsetof(ADSPCORE, sr.srx.sr0),
  644.     offsetof(ADSPCORE, sr.srx.sr1)
  645. };
  646.  
  647.  
  648.  
  649. /*===========================================================================
  650.     ALU operations (result in AR)
  651. ===========================================================================*/
  652.  
  653. void alu_op_ar(int op)
  654. {
  655.     INT32 xop = (op >> 8) & 7;
  656.     INT32 yop = (op >> 11) & 3;
  657.     INT32 res;
  658.     
  659.     switch ((op >> 13) & 15)
  660.     {
  661.         case 0x00:
  662.             /* Y                Clear when y = 0 */
  663.             res = ALU_GETYREG_UNSIGNED(yop);
  664.             CALC_NZ(res);
  665.             break;
  666.         case 0x01:
  667.             /* Y + 1            PASS 1 when y = 0 */
  668.             yop = ALU_GETYREG_UNSIGNED(yop);
  669.             res = yop + 1;
  670.             CALC_NZ(res);
  671.             if (yop == 0x7fff) SET_V;
  672.             else if (yop == 0xffff) SET_C;
  673.             break;
  674.         case 0x02:
  675.             /* X + Y + C */
  676.             xop = ALU_GETXREG_UNSIGNED(xop);
  677.             yop = ALU_GETYREG_UNSIGNED(yop);
  678.             yop += GET_C >> 3;
  679.             res = xop + yop;
  680.             CALC_NZVC(xop, yop, res);
  681.             break;
  682.         case 0x03:
  683.             /* X + Y            X when y = 0 */
  684.             xop = ALU_GETXREG_UNSIGNED(xop);
  685.             yop = ALU_GETYREG_UNSIGNED(yop);
  686.             res = xop + yop;
  687.             CALC_NZVC(xop, yop, res);
  688.             break;
  689.         case 0x04:
  690.             /* NOT Y */
  691.             res = ALU_GETYREG_UNSIGNED(yop) ^ 0xffff;
  692.             CALC_NZ(res);
  693.             break;
  694.         case 0x05:
  695.             /* -Y */
  696.             yop = ALU_GETYREG_UNSIGNED(yop);
  697.             res = -yop;
  698.             CALC_NZ(res);
  699.             if (yop == 0x8000) SET_V;
  700.             if (yop == 0x0000) SET_C;
  701.             break;
  702.         case 0x06:
  703.             /* X - Y + C - 1    X + C - 1 when y = 0 */
  704.             xop = ALU_GETXREG_UNSIGNED(xop);
  705.             yop = ALU_GETYREG_UNSIGNED(yop);
  706.             yop -= (GET_C >> 3) - 1;
  707.             res = xop - yop;
  708.             CALC_NZVC_SUB(xop, yop, res);
  709.             break;
  710.         case 0x07:
  711.             /* X - Y */
  712.             xop = ALU_GETXREG_UNSIGNED(xop);
  713.             yop = ALU_GETYREG_UNSIGNED(yop);
  714.             res = xop - yop;
  715.             CALC_NZVC_SUB(xop, yop, res);
  716.             break;
  717.         case 0x08:
  718.             /* Y - 1            PASS -1 when y = 0 */
  719.             yop = ALU_GETYREG_UNSIGNED(yop);
  720.             res = yop - 1;
  721.             CALC_NZ(res);
  722.             if (yop == 0x8000) SET_V;
  723.             else if (yop == 0x0000) SET_C;
  724.             break;
  725.         case 0x09:
  726.             /* Y - X            -X when y = 0 */
  727.             xop = ALU_GETXREG_UNSIGNED(xop);
  728.             yop = ALU_GETYREG_UNSIGNED(yop);
  729.             res = yop - xop;
  730.             CALC_NZVC_SUB(yop, xop, res);
  731.             break;
  732.         case 0x0a:
  733.             /* Y - X + C - 1    -X + C - 1 when y = 0 */
  734.             xop = ALU_GETXREG_UNSIGNED(xop);
  735.             yop = ALU_GETYREG_UNSIGNED(yop);
  736.             xop -= (GET_C >> 3) - 1;
  737.             res = yop - xop;
  738.             CALC_NZVC_SUB(yop, xop, res);
  739.             break;
  740.         case 0x0b:
  741.             /* NOT X */
  742.             res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
  743.             CALC_NZ(res);
  744.             break;
  745.         case 0x0c:
  746.             /* X AND Y */
  747.             xop = ALU_GETXREG_UNSIGNED(xop);
  748.             yop = ALU_GETYREG_UNSIGNED(yop);
  749.             res = xop & yop;
  750.             CALC_NZ(res);
  751.             break;
  752.         case 0x0d:
  753.             /* X OR Y */
  754.             xop = ALU_GETXREG_UNSIGNED(xop);
  755.             yop = ALU_GETYREG_UNSIGNED(yop);
  756.             res = xop | yop;
  757.             CALC_NZ(res);
  758.             break;
  759.         case 0x0e:
  760.             /* X XOR Y */
  761.             xop = ALU_GETXREG_UNSIGNED(xop);
  762.             yop = ALU_GETYREG_UNSIGNED(yop);
  763.             res = xop ^ yop;
  764.             CALC_NZ(res);
  765.             break;
  766.         case 0x0f:
  767.             /* ABS X */
  768.             xop = ALU_GETXREG_UNSIGNED(xop);
  769.             res = (xop & 0x8000) ? -xop : xop;
  770.             if (xop == 0) SET_Z;
  771.             if (xop == 0x8000) SET_N, SET_V;
  772.             CLR_S;
  773.             if (xop & 0x8000) SET_S;
  774.             break;
  775.         default:
  776.             res = 0;    /* just to keep the compiler happy */
  777.             break;
  778.     }
  779.  
  780.     /* saturate */
  781.     if ((adsp2100.mstat & MSTAT_SATURATE) && GET_V) res = GET_C ? -32768 : 32767;
  782.  
  783.     /* set the final value */    
  784.     core->ar.u = res;
  785. }
  786.  
  787.  
  788.  
  789. /*===========================================================================
  790.     ALU operations (result in AF)
  791. ===========================================================================*/
  792.  
  793. void alu_op_af(int op)
  794. {
  795.     INT32 xop = (op >> 8) & 7;
  796.     INT32 yop = (op >> 11) & 3;
  797.     INT32 res;
  798.     
  799.     switch ((op >> 13) & 15)
  800.     {
  801.         case 0x00:
  802.             /* Y                Clear when y = 0 */
  803.             res = ALU_GETYREG_UNSIGNED(yop);
  804.             CALC_NZ(res);
  805.             break;
  806.         case 0x01:
  807.             /* Y + 1            PASS 1 when y = 0 */
  808.             yop = ALU_GETYREG_UNSIGNED(yop);
  809.             res = yop + 1;
  810.             CALC_NZ(res);
  811.             if (yop == 0x7fff) SET_V;
  812.             else if (yop == 0xffff) SET_C;
  813.             break;
  814.         case 0x02:
  815.             /* X + Y + C */
  816.             xop = ALU_GETXREG_UNSIGNED(xop);
  817.             yop = ALU_GETYREG_UNSIGNED(yop);
  818.             yop += GET_C >> 3;
  819.             res = xop + yop;
  820.             CALC_NZVC(xop, yop, res);
  821.             break;
  822.         case 0x03:
  823.             /* X + Y            X when y = 0 */
  824.             xop = ALU_GETXREG_UNSIGNED(xop);
  825.             yop = ALU_GETYREG_UNSIGNED(yop);
  826.             res = xop + yop;
  827.             CALC_NZVC(xop, yop, res);
  828.             break;
  829.         case 0x04:
  830.             /* NOT Y */
  831.             res = ALU_GETYREG_UNSIGNED(yop) ^ 0xffff;
  832.             CALC_NZ(res);
  833.             break;
  834.         case 0x05:
  835.             /* -Y */
  836.             yop = ALU_GETYREG_UNSIGNED(yop);
  837.             res = -yop;
  838.             CALC_NZ(res);
  839.             if (yop == 0x8000) SET_V;
  840.             if (yop == 0x0000) SET_C;
  841.             break;
  842.         case 0x06:
  843.             /* X - Y + C - 1    X + C - 1 when y = 0 */
  844.             xop = ALU_GETXREG_UNSIGNED(xop);
  845.             yop = ALU_GETYREG_UNSIGNED(yop);
  846.             yop -= (GET_C >> 3) - 1;
  847.             res = xop - yop;
  848.             CALC_NZVC_SUB(xop, yop, res);
  849.             break;
  850.         case 0x07:
  851.             /* X - Y */
  852.             xop = ALU_GETXREG_UNSIGNED(xop);
  853.             yop = ALU_GETYREG_UNSIGNED(yop);
  854.             res = xop - yop;
  855.             CALC_NZVC_SUB(xop, yop, res);
  856.             break;
  857.         case 0x08:
  858.             /* Y - 1            PASS -1 when y = 0 */
  859.             yop = ALU_GETYREG_UNSIGNED(yop);
  860.             res = yop - 1;
  861.             CALC_NZ(res);
  862.             if (yop == 0x8000) SET_V;
  863.             else if (yop == 0x0000) SET_C;
  864.             break;
  865.         case 0x09:
  866.             /* Y - X            -X when y = 0 */
  867.             xop = ALU_GETXREG_UNSIGNED(xop);
  868.             yop = ALU_GETYREG_UNSIGNED(yop);
  869.             res = yop - xop;
  870.             CALC_NZVC_SUB(yop, xop, res);
  871.             break;
  872.         case 0x0a:
  873.             /* Y - X + C - 1    -X + C - 1 when y = 0 */
  874.             xop = ALU_GETXREG_UNSIGNED(xop);
  875.             yop = ALU_GETYREG_UNSIGNED(yop);
  876.             xop -= (GET_C >> 3) - 1;
  877.             res = yop - xop;
  878.             CALC_NZVC_SUB(yop, xop, res);
  879.             break;
  880.         case 0x0b:
  881.             /* NOT X */
  882.             res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
  883.             CALC_NZ(res);
  884.             break;
  885.         case 0x0c:
  886.             /* X AND Y */
  887.             xop = ALU_GETXREG_UNSIGNED(xop);
  888.             yop = ALU_GETYREG_UNSIGNED(yop);
  889.             res = xop & yop;
  890.             CALC_NZ(res);
  891.             break;
  892.         case 0x0d:
  893.             /* X OR Y */
  894.             xop = ALU_GETXREG_UNSIGNED(xop);
  895.             yop = ALU_GETYREG_UNSIGNED(yop);
  896.             res = xop | yop;
  897.             CALC_NZ(res);
  898.             break;
  899.         case 0x0e:
  900.             /* X XOR Y */
  901.             xop = ALU_GETXREG_UNSIGNED(xop);
  902.             yop = ALU_GETYREG_UNSIGNED(yop);
  903.             res = xop ^ yop;
  904.             CALC_NZ(res);
  905.             break;
  906.         case 0x0f:
  907.             /* ABS X */
  908.             xop = ALU_GETXREG_UNSIGNED(xop);
  909.             res = (xop & 0x8000) ? -xop : xop;
  910.             if (xop == 0) SET_Z;
  911.             if (xop == 0x8000) SET_N, SET_V;
  912.             CLR_S;
  913.             if (xop & 0x8000) SET_S;
  914.             break;
  915.         default:
  916.             res = 0;    /* just to keep the compiler happy */
  917.             break;
  918.     }
  919.  
  920.     /* set the final value */    
  921.     core->af.u = res;
  922. }
  923.  
  924.  
  925.  
  926. /*===========================================================================
  927.     MAC operations (result in MR)
  928. ===========================================================================*/
  929.  
  930. void mac_op_mr(int op)
  931. {
  932. #if SUPPORT_2101_EXTENSIONS
  933.     INT8 shift = ((adsp2100.mstat & MSTAT_INTEGER) >> 4) ^ 1;
  934. #else
  935.     INT8 shift = 1;
  936. #endif
  937.     INT32 xop = (op >> 8) & 7;
  938.     INT32 yop = (op >> 11) & 3;
  939.     INT32 temp;
  940.     UINT32 tempu;
  941.     INT64 res;
  942.     
  943.     switch ((op >> 13) & 15)
  944.     {
  945.         case 0x00:
  946.             /* no-op */
  947.             return;
  948.         case 0x01:
  949.             /* X * Y (RND) */
  950.             xop = MAC_GETXREG_SIGNED(xop);
  951.             yop = MAC_GETYREG_SIGNED(yop);
  952.             temp = (xop * yop) << shift;
  953.             res = (INT64)temp;
  954.             if ((res & 0xffff) == 0x8000) res &= ~0x10000;
  955.             else res += (res & 0x8000) << 1;
  956.             break;
  957.         case 0x02:
  958.             /* MR + X * Y (RND) */
  959.             xop = MAC_GETXREG_SIGNED(xop);
  960.             yop = MAC_GETYREG_SIGNED(yop);
  961.             temp = (xop * yop) << shift;
  962.             res = core->mr.mr + (INT64)temp;
  963.             if ((res & 0xffff) == 0x8000) res &= ~0x10000;
  964.             else res += (res & 0x8000) << 1;
  965.             break;
  966.         case 0x03:
  967.             /* MR - X * Y (RND) */
  968.             xop = MAC_GETXREG_SIGNED(xop);
  969.             yop = MAC_GETYREG_SIGNED(yop);
  970.             temp = (xop * yop) << shift;
  971.             res = core->mr.mr - (INT64)temp;
  972.             if ((res & 0xffff) == 0x8000) res &= ~0x10000;
  973.             else res += (res & 0x8000) << 1;
  974.             break;
  975.         case 0x04:
  976.             /* X * Y (SS)        Clear when y = 0 */
  977.             xop = MAC_GETXREG_SIGNED(xop);
  978.             yop = MAC_GETYREG_SIGNED(yop);
  979.             temp = (xop * yop) << shift;
  980.             res = (INT64)temp;
  981.             break;
  982.         case 0x05:
  983.             /* X * Y (SU) */
  984.             xop = MAC_GETXREG_SIGNED(xop);
  985.             yop = MAC_GETYREG_UNSIGNED(yop);
  986.             temp = (xop * yop) << shift;
  987.             res = (INT64)temp;
  988.             break;
  989.         case 0x06:
  990.             /* X * Y (US) */
  991.             xop = MAC_GETXREG_UNSIGNED(xop);
  992.             yop = MAC_GETYREG_SIGNED(yop);
  993.             temp = (xop * yop) << shift;
  994.             res = (INT64)temp;
  995.             break;
  996.         case 0x07:
  997.             /* X * Y (UU) */
  998.             xop = MAC_GETXREG_UNSIGNED(xop);
  999.             yop = MAC_GETYREG_UNSIGNED(yop);
  1000.             tempu = ((UINT16)xop * (UINT16)yop) << shift;
  1001.             res = (INT64)tempu;
  1002.             break;
  1003.         case 0x08:
  1004.             /* MR + X * Y (SS) */
  1005.             xop = MAC_GETXREG_SIGNED(xop);
  1006.             yop = MAC_GETYREG_SIGNED(yop);
  1007.             temp = (xop * yop) << shift;
  1008.             res = core->mr.mr + (INT64)temp;
  1009.             break;
  1010.         case 0x09:
  1011.             /* MR + X * Y (SU) */
  1012.             xop = MAC_GETXREG_SIGNED(xop);
  1013.             yop = MAC_GETYREG_UNSIGNED(yop);
  1014.             temp = (xop * yop) << shift;
  1015.             res = core->mr.mr + (INT64)temp;
  1016.             break;
  1017.         case 0x0a:
  1018.             /* MR + X * Y (US) */
  1019.             xop = MAC_GETXREG_UNSIGNED(xop);
  1020.             yop = MAC_GETYREG_SIGNED(yop);
  1021.             temp = (xop * yop) << shift;
  1022.             res = core->mr.mr + (INT64)temp;
  1023.             break;
  1024.         case 0x0b:
  1025.             /* MR + X * Y (UU) */
  1026.             xop = MAC_GETXREG_UNSIGNED(xop);
  1027.             yop = MAC_GETYREG_UNSIGNED(yop);
  1028.             tempu = ((UINT16)xop * (UINT16)yop) << shift;
  1029.             res = core->mr.mr + (INT64)tempu;
  1030.             break;
  1031.         case 0x0c:
  1032.             /* MR - X * Y (SS) */
  1033.             xop = MAC_GETXREG_SIGNED(xop);
  1034.             yop = MAC_GETYREG_SIGNED(yop);
  1035.             temp = (xop * yop) << shift;
  1036.             res = core->mr.mr - (INT64)temp;
  1037.             break;
  1038.         case 0x0d:
  1039.             /* MR - X * Y (SU) */
  1040.             xop = MAC_GETXREG_SIGNED(xop);
  1041.             yop = MAC_GETYREG_UNSIGNED(yop);
  1042.             temp = (xop * yop) << shift;
  1043.             res = core->mr.mr - (INT64)temp;
  1044.             break;
  1045.         case 0x0e:
  1046.             /* MR - X * Y (US) */
  1047.             xop = MAC_GETXREG_UNSIGNED(xop);
  1048.             yop = MAC_GETYREG_SIGNED(yop);
  1049.             temp = (xop * yop) << shift;
  1050.             res = core->mr.mr - (INT64)temp;
  1051.             break;
  1052.         case 0x0f:
  1053.             /* MR - X * Y (UU) */
  1054.             xop = MAC_GETXREG_UNSIGNED(xop);
  1055.             yop = MAC_GETYREG_UNSIGNED(yop);
  1056.             tempu = ((UINT16)xop * (UINT16)yop) << shift;
  1057.             res = core->mr.mr - (INT64)tempu;
  1058.             break;
  1059.         default:
  1060.             res = 0;    /* just to keep the compiler happy */
  1061.             break;
  1062.     }
  1063.  
  1064.     /* set the final value */
  1065.     temp = (res >> 31) & 0x1ff;
  1066.     CLR_MV;
  1067.     if (temp != 0x000 && temp != 0x1ff) SET_MV;
  1068.     core->mr.mr = res;
  1069.     core->mr.mrx.mrzero.u = 0;
  1070. }
  1071.  
  1072.  
  1073.  
  1074. /*===========================================================================
  1075.     MAC operations (result in MF)
  1076. ===========================================================================*/
  1077.  
  1078. void mac_op_mf(int op)
  1079. {
  1080. #if SUPPORT_2101_EXTENSIONS
  1081.     INT8 shift = ((adsp2100.mstat & MSTAT_INTEGER) >> 4) ^ 1;
  1082. #else
  1083.     INT8 shift = 1;
  1084. #endif
  1085.     INT32 xop = (op >> 8) & 7;
  1086.     INT32 yop = (op >> 11) & 3;
  1087.     INT32 temp;
  1088.     UINT32 tempu;
  1089.     INT64 res;
  1090.     
  1091.     switch ((op >> 13) & 15)
  1092.     {
  1093.         case 0x00:
  1094.             /* no-op */
  1095.             return;
  1096.         case 0x01:
  1097.             /* X * Y (RND) */
  1098.             xop = MAC_GETXREG_SIGNED(xop);
  1099.             yop = MAC_GETYREG_SIGNED(yop);
  1100.             temp = (xop * yop) << shift;
  1101.             res = (INT64)temp;
  1102.             if ((res & 0xffff) == 0x8000) res &= ~0x10000;
  1103.             else res += (res & 0x8000) << 1;
  1104.             break;
  1105.         case 0x02:
  1106.             /* MR + X * Y (RND) */
  1107.             xop = MAC_GETXREG_SIGNED(xop);
  1108.             yop = MAC_GETYREG_SIGNED(yop);
  1109.             temp = (xop * yop) << shift;
  1110.             res = core->mr.mr + (INT64)temp;
  1111.             if ((res & 0xffff) == 0x8000) res &= ~0x10000;
  1112.             else res += (res & 0x8000) << 1;
  1113.             break;
  1114.         case 0x03:
  1115.             /* MR - X * Y (RND) */
  1116.             xop = MAC_GETXREG_SIGNED(xop);
  1117.             yop = MAC_GETYREG_SIGNED(yop);
  1118.             temp = (xop * yop) << shift;
  1119.             res = core->mr.mr - (INT64)temp;
  1120.             if ((res & 0xffff) == 0x8000) res &= ~0x10000;
  1121.             else res += (res & 0x8000) << 1;
  1122.             break;
  1123.         case 0x04:
  1124.             /* X * Y (SS)        Clear when y = 0 */
  1125.             xop = MAC_GETXREG_SIGNED(xop);
  1126.             yop = MAC_GETYREG_SIGNED(yop);
  1127.             temp = (xop * yop) << shift;
  1128.             res = (INT64)temp;
  1129.             break;
  1130.         case 0x05:
  1131.             /* X * Y (SU) */
  1132.             xop = MAC_GETXREG_SIGNED(xop);
  1133.             yop = MAC_GETYREG_UNSIGNED(yop);
  1134.             temp = (xop * yop) << shift;
  1135.             res = (INT64)temp;
  1136.             break;
  1137.         case 0x06:
  1138.             /* X * Y (US) */
  1139.             xop = MAC_GETXREG_UNSIGNED(xop);
  1140.             yop = MAC_GETYREG_SIGNED(yop);
  1141.             temp = (xop * yop) << shift;
  1142.             res = (INT64)temp;
  1143.             break;
  1144.         case 0x07:
  1145.             /* X * Y (UU) */
  1146.             xop = MAC_GETXREG_UNSIGNED(xop);
  1147.             yop = MAC_GETYREG_UNSIGNED(yop);
  1148.             tempu = ((UINT16)xop * (UINT16)yop) << shift;
  1149.             res = (INT64)tempu;
  1150.             break;
  1151.         case 0x08:
  1152.             /* MR + X * Y (SS) */
  1153.             xop = MAC_GETXREG_SIGNED(xop);
  1154.             yop = MAC_GETYREG_SIGNED(yop);
  1155.             temp = (xop * yop) << shift;
  1156.             res = core->mr.mr + (INT64)temp;
  1157.             break;
  1158.         case 0x09:
  1159.             /* MR + X * Y (SU) */
  1160.             xop = MAC_GETXREG_SIGNED(xop);
  1161.             yop = MAC_GETYREG_UNSIGNED(yop);
  1162.             temp = (xop * yop) << shift;
  1163.             res = core->mr.mr + (INT64)temp;
  1164.             break;
  1165.         case 0x0a:
  1166.             /* MR + X * Y (US) */
  1167.             xop = MAC_GETXREG_UNSIGNED(xop);
  1168.             yop = MAC_GETYREG_SIGNED(yop);
  1169.             temp = (xop * yop) << shift;
  1170.             res = core->mr.mr + (INT64)temp;
  1171.             break;
  1172.         case 0x0b:
  1173.             /* MR + X * Y (UU) */
  1174.             xop = MAC_GETXREG_UNSIGNED(xop);
  1175.             yop = MAC_GETYREG_UNSIGNED(yop);
  1176.             tempu = ((UINT16)xop * (UINT16)yop) << shift;
  1177.             res = core->mr.mr + (INT64)tempu;
  1178.             break;
  1179.         case 0x0c:
  1180.             /* MR - X * Y (SS) */
  1181.             xop = MAC_GETXREG_SIGNED(xop);
  1182.             yop = MAC_GETYREG_SIGNED(yop);
  1183.             temp = (xop * yop) << shift;
  1184.             res = core->mr.mr - (INT64)temp;
  1185.             break;
  1186.         case 0x0d:
  1187.             /* MR - X * Y (SU) */
  1188.             xop = MAC_GETXREG_SIGNED(xop);
  1189.             yop = MAC_GETYREG_UNSIGNED(yop);
  1190.             temp = (xop * yop) << shift;
  1191.             res = core->mr.mr - (INT64)temp;
  1192.             break;
  1193.         case 0x0e:
  1194.             /* MR - X * Y (US) */
  1195.             xop = MAC_GETXREG_UNSIGNED(xop);
  1196.             yop = MAC_GETYREG_SIGNED(yop);
  1197.             temp = (xop * yop) << shift;
  1198.             res = core->mr.mr - (INT64)temp;
  1199.             break;
  1200.         case 0x0f:
  1201.             /* MR - X * Y (UU) */
  1202.             xop = MAC_GETXREG_UNSIGNED(xop);
  1203.             yop = MAC_GETYREG_UNSIGNED(yop);
  1204.             tempu = ((UINT16)xop * (UINT16)yop) << shift;
  1205.             res = core->mr.mr - (INT64)tempu;
  1206.             break;
  1207.         default:
  1208.             res = 0;    /* just to keep the compiler happy */
  1209.             break;
  1210.     }
  1211.  
  1212.     /* set the final value */
  1213.     core->mf.u = (UINT32)res >> 16;
  1214. }
  1215.  
  1216.  
  1217.  
  1218. /*===========================================================================
  1219.     SHIFT operations (result in SR/SE/SB)
  1220. ===========================================================================*/
  1221.  
  1222. void shift_op(int op)
  1223. {
  1224.     INT8 sc = core->se.s;
  1225.     INT32 xop = (op >> 8) & 7;
  1226.     UINT32 res;
  1227.     
  1228.     switch ((op >> 11) & 15)
  1229.     {
  1230.         case 0x00:
  1231.             /* LSHIFT (HI) */
  1232.             xop = SHIFT_GETXREG_UNSIGNED(xop) << 16;
  1233.             if (sc > 0) res = xop << sc;
  1234.             else res = (UINT32)xop >> -sc;
  1235.             core->sr.sr = res;
  1236.             break;
  1237.         case 0x01:
  1238.             /* LSHIFT (HI, OR) */
  1239.             xop = SHIFT_GETXREG_UNSIGNED(xop) << 16;
  1240.             if (sc > 0) res = xop << sc;
  1241.             else res = (UINT32)xop >> -sc;
  1242.             core->sr.sr |= res;
  1243.             break;
  1244.         case 0x02:
  1245.             /* LSHIFT (LO) */
  1246.             xop = SHIFT_GETXREG_UNSIGNED(xop);
  1247.             if (sc > 0) res = xop << sc;
  1248.             else res = xop >> -sc;
  1249.             core->sr.sr = res;
  1250.             break;
  1251.         case 0x03:
  1252.             /* LSHIFT (LO, OR) */
  1253.             xop = SHIFT_GETXREG_UNSIGNED(xop);
  1254.             if (sc > 0) res = xop << sc;
  1255.             else res = xop >> -sc;
  1256.             core->sr.sr |= res;
  1257.             break;
  1258.         case 0x04:
  1259.             /* ASHIFT (HI) */
  1260.             xop = SHIFT_GETXREG_SIGNED(xop) << 16;
  1261.             if (sc > 0) res = xop << sc;
  1262.             else res = xop >> -sc;
  1263.             core->sr.sr = res;
  1264.             break;
  1265.         case 0x05:
  1266.             /* ASHIFT (HI, OR) */
  1267.             xop = SHIFT_GETXREG_SIGNED(xop) << 16;
  1268.             if (sc > 0) res = xop << sc;
  1269.             else res = xop >> -sc;
  1270.             core->sr.sr |= res;
  1271.             break;
  1272.         case 0x06:
  1273.             /* ASHIFT (LO) */
  1274.             xop = SHIFT_GETXREG_SIGNED(xop);
  1275.             if (sc > 0) res = xop << sc;
  1276.             else res = xop >> -sc;
  1277.             core->sr.sr = res;
  1278.             break;
  1279.         case 0x07:
  1280.             /* ASHIFT (LO, OR) */
  1281.             xop = SHIFT_GETXREG_SIGNED(xop);
  1282.             if (sc > 0) res = xop << sc;
  1283.             else res = xop >> -sc;
  1284.             core->sr.sr |= res;
  1285.             break;
  1286.         case 0x08:
  1287.             /* NORM (HI) */
  1288.             xop = SHIFT_GETXREG_SIGNED(xop) << 16;
  1289.             if (sc > 0) 
  1290.             { 
  1291.                 xop = ((UINT32)xop >> 1) | ((adsp2100.astat & CFLAG) << 28); 
  1292.                 res = xop >> (sc - 1);
  1293.             }
  1294.             else res = xop << -sc;
  1295.             core->sr.sr = res;
  1296.             break;
  1297.         case 0x09:
  1298.             /* NORM (HI, OR) */
  1299.             xop = SHIFT_GETXREG_SIGNED(xop) << 16;
  1300.             if (sc > 0) 
  1301.             { 
  1302.                 xop = ((UINT32)xop >> 1) | ((adsp2100.astat & CFLAG) << 28); 
  1303.                 res = xop >> (sc - 1);
  1304.             }
  1305.             else res = xop << -sc;
  1306.             core->sr.sr |= res;
  1307.             break;
  1308.         case 0x0a:
  1309.             /* NORM (LO) */
  1310.             xop = SHIFT_GETXREG_UNSIGNED(xop);
  1311.             if (sc > 0) res = xop >> sc;
  1312.             else res = xop << -sc;
  1313.             core->sr.sr = res;
  1314.             break;
  1315.         case 0x0b:
  1316.             /* NORM (LO, OR) */
  1317.             xop = SHIFT_GETXREG_UNSIGNED(xop);
  1318.             if (sc > 0) res = xop >> sc;
  1319.             else res = xop << -sc;
  1320.             core->sr.sr |= res;
  1321.             break;
  1322.         case 0x0c:
  1323.             /* EXP (HI) */
  1324.             xop = SHIFT_GETXREG_SIGNED(xop) << 16;
  1325.             res = 0;
  1326.             if (xop < 0)
  1327.             {
  1328.                 SET_SS;
  1329.                 while ((xop & 0x40000000) != 0) res++, xop <<= 1;
  1330.             }
  1331.             else
  1332.             {
  1333.                 CLR_SS;
  1334.                 xop |= 0x8000;
  1335.                 while ((xop & 0x40000000) == 0) res++, xop <<= 1;
  1336.             }
  1337.             core->se.s = -res;
  1338.             break;
  1339.         case 0x0d:
  1340.             /* EXP (HIX) */
  1341.             xop = SHIFT_GETXREG_SIGNED(xop) << 16;
  1342.             if (GET_V)
  1343.             {
  1344.                 core->se.s = 1;
  1345.                 if (xop < 0) CLR_SS;
  1346.                 else SET_SS;
  1347.             }
  1348.             else
  1349.             {
  1350.                 res = 0;
  1351.                 if (xop < 0)
  1352.                 {
  1353.                     SET_SS;
  1354.                     while ((xop & 0x40000000) != 0) res++, xop <<= 1;
  1355.                 }
  1356.                 else
  1357.                 {
  1358.                     CLR_SS;
  1359.                     xop |= 0x8000;
  1360.                     while ((xop & 0x40000000) == 0) res++, xop <<= 1;
  1361.                 }
  1362.                 core->se.s = -res;
  1363.             }
  1364.             break;
  1365.         case 0x0e:
  1366.             /* EXP (LO) */
  1367.             if (core->se.s == -15)
  1368.             {
  1369.                 xop = SHIFT_GETXREG_SIGNED(xop);
  1370.                 res = 15;
  1371.                 if (GET_SS)
  1372.                     while ((xop & 0x8000) != 0) res++, xop <<= 1;
  1373.                 else
  1374.                 {
  1375.                     xop = (xop << 1) | 1;
  1376.                     while ((xop & 0x10000) == 0) res++, xop <<= 1;
  1377.                 }
  1378.                 core->se.s = -res;
  1379.             }
  1380.             break;
  1381.         case 0x0f:
  1382.             /* EXPADJ */
  1383.             xop = SHIFT_GETXREG_SIGNED(xop) << 16;
  1384.             res = 0;
  1385.             if (xop < 0)
  1386.                 while ((xop & 0x40000000) != 0) res++, xop <<= 1;
  1387.             else
  1388.             {
  1389.                 xop |= 0x8000;
  1390.                 while ((xop & 0x40000000) == 0) res++, xop <<= 1;
  1391.             }
  1392.             if (res < -core->sb.s)
  1393.                 core->sb.s = -res;
  1394.             break;
  1395.     }
  1396. }
  1397.  
  1398.  
  1399.  
  1400. /*===========================================================================
  1401.     Immediate SHIFT operations (result in SR/SE/SB)
  1402. ===========================================================================*/
  1403.  
  1404. void shift_op_imm(int op)
  1405. {
  1406.     INT8 sc = (INT8)op;
  1407.     INT32 xop = (op >> 8) & 7;
  1408.     UINT32 res;
  1409.     
  1410.     switch ((op >> 11) & 15)
  1411.     {
  1412.         case 0x00:
  1413.             /* LSHIFT (HI) */
  1414.             xop = SHIFT_GETXREG_UNSIGNED(xop) << 16;
  1415.             if (sc > 0) res = xop << sc;
  1416.             else res = (UINT32)xop >> -sc;
  1417.             core->sr.sr = res;
  1418.             break;
  1419.         case 0x01:
  1420.             /* LSHIFT (HI, OR) */
  1421.             xop = SHIFT_GETXREG_UNSIGNED(xop) << 16;
  1422.             if (sc > 0) res = xop << sc;
  1423.             else res = (UINT32)xop >> -sc;
  1424.             core->sr.sr |= res;
  1425.             break;
  1426.         case 0x02:
  1427.             /* LSHIFT (LO) */
  1428.             xop = SHIFT_GETXREG_UNSIGNED(xop);
  1429.             if (sc > 0) res = xop << sc;
  1430.             else res = xop >> -sc;
  1431.             core->sr.sr = res;
  1432.             break;
  1433.         case 0x03:
  1434.             /* LSHIFT (LO, OR) */
  1435.             xop = SHIFT_GETXREG_UNSIGNED(xop);
  1436.             if (sc > 0) res = xop << sc;
  1437.             else res = xop >> -sc;
  1438.             core->sr.sr |= res;
  1439.             break;
  1440.         case 0x04:
  1441.             /* ASHIFT (HI) */
  1442.             xop = SHIFT_GETXREG_SIGNED(xop) << 16;
  1443.             if (sc > 0) res = xop << sc;
  1444.             else res = xop >> -sc;
  1445.             core->sr.sr = res;
  1446.             break;
  1447.         case 0x05:
  1448.             /* ASHIFT (HI, OR) */
  1449.             xop = SHIFT_GETXREG_SIGNED(xop) << 16;
  1450.             if (sc > 0) res = xop << sc;
  1451.             else res = xop >> -sc;
  1452.             core->sr.sr |= res;
  1453.             break;
  1454.         case 0x06:
  1455.             /* ASHIFT (LO) */
  1456.             xop = SHIFT_GETXREG_SIGNED(xop);
  1457.             if (sc > 0) res = xop << sc;
  1458.             else res = xop >> -sc;
  1459.             core->sr.sr = res;
  1460.             break;
  1461.         case 0x07:
  1462.             /* ASHIFT (LO, OR) */
  1463.             xop = SHIFT_GETXREG_SIGNED(xop);
  1464.             if (sc > 0) res = xop << sc;
  1465.             else res = xop >> -sc;
  1466.             core->sr.sr |= res;
  1467.             break;
  1468.     }
  1469. }
  1470.